#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

#include "global.h"
#include "constantes.h"
#include "sockets.h"
#include "NIPC.h"
#include "listas.h"
#include "sincronizador.h"


extern int numeroSincro;
extern int contador;
int owner;
	
void *syncer(void *args) {
    
	disco * dsk = (struct DiscoConocido *) args;	
	
	numeroSincro++;
	owner = numeroSincro;
	int i,j,ret,flag,salto;
	int a,enviados;
	
	char* vacia=(char *)malloc(512);
	memset(vacia,'\0',512);
	
	while(dsk->sectores < 800000)
	{
		a=0;
		if(enviados!=800000){
			while(a<8){
				disco* discoElegido = (disco*)asignarread(enviados, owner);
				a++;
				enviados++;
			}
		}
		
		
		salto=0;
		flag=0;
		
		while(!flag){
			
				
			pedido *nodo = (pedido *)BuscarPedidoEnListaDeDisco_Lect3(colaGlobal,colaGlobal_Ult);
			if(nodo != NULL){
				
				SacarNodoDescriptoresDeLista2(&nodo, &(colaGlobal),&(colaGlobal_Ult));
				
				if(!(strcmp(nodo->data,vacia))){
					dsk->sectores++;
					salto=1;
				}
				else
					asignarwrite(dsk,owner,nodo->numeroSector,nodo->data);
				
				free(nodo);
				flag=1;
			}					
			
		}
			
			
		flag=0;
		
		if(salto)
			salto=0;
		else
		{	
			while(!flag){	
				
			
				struct ListaIDdescriptors *nodo=BuscarPedidoEnListaDeDisco_Escr2(colaGlobal,colaGlobal_Ult);
				if(nodo != NULL){
					SacarNodoDescriptoresDeLista2(&nodo, &colaGlobal,&(colaGlobal_Ult));
					free(nodo);
					dsk->pendings--;
					dsk->sectores++;
					flag=1;
				}

	
			}
		}
		
		if(dsk->sectores==100000 || dsk->sectores==200000 || dsk->sectores==300000  || dsk->sectores==400000  || dsk->sectores==500000  || dsk->sectores==600000  || dsk->sectores==700000  || dsk->sectores==800000  || dsk->sectores==900000  || dsk->sectores==1000000 )
			printf("Se sincronizaron los primeros %i sectores\n",dsk->sectores);
	
	}
	
	printf("Se finalizo la sincronizacion del disco %s\n", dsk->sNombre);
	dsk->Estado = LISTO;
	printf("DISCO LISTO\n");

}


disco* asignarread(int sector, int owner) {
    
	char * sContador=(char*)malloc(20);
	int payload;
	char *sAux=(char *)malloc(20);
	int ret;
	int tamanio_buff ;
	char *buffer;
	
	disco *dsk = (disco *)BuscarDiscoPorNombre("Disco1");
	
	
	if(pthread_mutex_lock(&(mutex3))!=0){
		perror("pthread_mutex_lock");
		exit(EXIT_FAILURE);
	}
			
	contador++;			
			
	if(pthread_mutex_unlock(&(mutex3))!=0){
		perror("pthread_mutex_lock");
		exit(EXIT_FAILURE);
	}
	
	
	intacad(contador,sContador);
	dsk->pendings++;
	memset(sAux,'\0',20);
	intacad(sector,sAux);	
	payload=READ_SECTORSYNC_REQUEST;
	tamanio_buff = strlen(sContador) + 1 + strlen(sAux) + 2 ;
	buffer = (char *) malloc (sizeof(char) * tamanio_buff);
	strcpy(buffer, sContador);
	strcat(buffer, ",");
	strcat(buffer, sAux);
	strcat(buffer, ";");
	InfoIPC rInfoIPC3;
	rInfoIPC3.payLoadLength=tamanio_buff;
	generarStructIPC(buffer,payload,&rInfoIPC3);
	enviarIPC(dsk->iSocketHDAParaDA,&rInfoIPC3);	
	free(rInfoIPC3.payload);
	free(buffer);
	free(sAux);
	free(sContador);
	
	return dsk;
}

void asignarwrite(struct DiscoConocido *dsk, int owner,int sector,char *data) {
	
	char * sContador=(char*)malloc(20);
	int payload;
	char *sAux=(char *)malloc(20);
	int ret; 
	int tamanio_buff ;
	char *buffer; 
	 
	

	if(pthread_mutex_lock(&(mutex3))!=0){
		perror("pthread_mutex_lock");
		exit(EXIT_FAILURE);
	}
	
	contador++;			
		
	if(pthread_mutex_unlock(&(mutex3))!=0){
		perror("pthread_mutex_lock");
		exit(EXIT_FAILURE);
	}
	
	
	intacad(contador,sContador);
	dsk->pendings++;
	memset(sAux,'\0',20);
	intacad(sector,sAux);	
	payload=WRITE_SECTORSYNC_REQUEST;
	tamanio_buff = strlen(sContador) + 1 + strlen(sAux) + 1 + 512 + 1;
	buffer = (char *) malloc (sizeof(char) * tamanio_buff);
	strcpy(buffer, sContador);
	strcat(buffer, ",");
	strcat(buffer, sAux);
	strcat(buffer, ";");
	memcpy(buffer + strlen(sContador) + 1 + strlen(sAux) + 1, data, 512);
	InfoIPC rInfoIPC3;
	rInfoIPC3.payLoadLength=tamanio_buff;
	generarStructIPC(buffer,payload,&rInfoIPC3);
	enviarIPC(dsk->iSocketHDAParaDA,&rInfoIPC3);	
	free(rInfoIPC3.payload);
	free(buffer);
	free(sAux);
	free(sContador);
	
}
